<template>
  <div class="edit-shell">
    <div class="editor-tool">
      <Toolbar
          :editor="editorRef"
          :defaultConfig="toolbarConfig"
          :mode="mode"
      />
    </div>
    <div class="editor">
      <Editor
          class="edit-content"
          v-model="valueHtml"
          :defaultConfig="editorConfig"
          :mode="mode"
          @onCreated="handleCreated"
      />
    </div>
    <div ref="options" class="article-options">
      <h1>发布设置</h1>
      <el-form ref="form" :model="formData" :rules="rules" label-width="auto" label-position="left">
        <el-form-item label="标题：" prop="title">
          <el-input class="title" v-model="formData.title"/>
        </el-form-item>
        <el-form-item label="板块：" prop="boardId">
          <el-cascader
              v-model="selectedBoardId"
              :options="boards"
              placeholder="选择板块"
              @change="onChooseBoard"
              filterable
              clearable
          />
        </el-form-item>
        <el-form-item label="封面：">
          <el-upload
              class="uploader"
              ref="loader"
              :action="policy.host"
              :data="policy"
              :show-file-list="false"
              :auto-upload="false"
              :on-change="handleChoose"
          >
            <img v-if="selectedFile.url" :src="selectedFile.url" class="avatar"/>
            <el-icon v-else class="avatar-uploader-icon">
              <Plus/>
            </el-icon>
          </el-upload>
        </el-form-item>
        <el-form-item label="摘要：" prop="summary">
          <el-input type="textarea" style="width: 500px;" autosize v-model="formData.summary"/>
        </el-form-item>
      </el-form>

    </div>
    <div class="footer-shell">
      <div class="footer">
        <div class="left" @click="handleViewRoll">
          <a v-show="!optionsVisibility">
            发布设置
            <el-icon>
              <arrow-down/>
            </el-icon>
          </a>
          <a v-show="optionsVisibility">
            回到顶部
            <el-icon>
              <arrow-up/>
            </el-icon>
          </a>
        </div>
        <div class="right">
          <span>字数：0</span>
          <el-button type="primary">预览</el-button>
          <el-button type="primary" @click="handleSubmit($refs.loader,$refs.form)">发布</el-button>
        </div>
      </div>


    </div>
  </div>


</template>

<script setup>
import '@wangeditor/editor/dist/css/style.css' // 引入 css
import {onBeforeUnmount, onMounted, ref, shallowRef, watch} from 'vue'
import {Editor, Toolbar} from '@wangeditor/editor-for-vue'
import {ArrowDown, ArrowUp, Plus} from "@element-plus/icons-vue";
import {useBoardStore} from "@/store/boardStore.js"
import {ElLoading, ElMessage} from "element-plus";
import {addArticleApi} from "@/api/articleApi.js";
import {getOssPolicyApi} from "@/api/fileUploadApi.js";
import {clearObj} from "@/utils/myUtils.js";
import {useElementVisibility} from "@vueuse/core";
import router from "@/router/router.js";


/**
 * 表单对象
 */
const formData = ref({
  title: '',  // 标题
  boardId: '', // 板块id
  boardName: '', //板块名称
  pBoardId: '', //父板块id
  pBoardName: '',//父板块名称
  cover: '',  // 封面url
  summary: '', // 摘要
  content: '' // 文章内容
})
/**
 * 表单校验规则
 */
const rules = ({
  title: [
    {required: true, message: '标题不能为空', trigger: 'blur'},
    {min: 5, max: 20, message: "标题长度为5-20个字符", trigger: "blur"}
  ],
  boardId: [
    {required: true, message: '请选择板块', trigger: 'blur'}
  ],
  cover: [
    {required: true, message: '请选择封面', trigger: 'blur'}
  ],
  summary: [
    {required: true, message: '请输入帖子摘要', trigger: 'blur'}
  ],
})

const boardStore = useBoardStore(); // 板块源数据
let selectedBoardId = ref([]) // 选中的板块id数组
let boards = ref([]) // 级联选择器展示数据

onMounted(() => {
  boards.value = getBoardChild(boardStore.boardList)
})


/**
 * 阿里云oss签名对象
 */
let policy = ref({
  OSSAccessKeyId: '',
  policy: '',
  signature: '',
  dir: '',
  key: '',
  host: '',
  success_action_status: '200',
  expire: '' // 签名过期时间
})
/**
 * 本地选的文件对象
 */
let selectedFile = ref({
  filename: '',
  url: ''
})

/**
 * 选择本地图片后的回调
 */
async function handleChoose(e) {
  console.log(e)
  if (e.status !== 'ready') return // 判断选择的文件状态，防止重复触发事件
  if (e.raw.type !== 'image/jpeg') {
    ElMessage.error('头像仅支持JPG格式!')
    return false
  } else if (e.raw.size / 1024 / 1024 > 2) {
    ElMessage.error('头像大小不能超过2MB!')
    return false
  }
  // createObjectURL，接受一个 Blob 实例作为参数，返回一个 URL 对象
  selectedFile.value.url = URL.createObjectURL(e.raw);
  selectedFile.value.filename = e.name
}

/**
 * 上传图片
 */
const handleUpload = async (uploader) => {
  //获取oss签名
  let response = await getOssPolicyApi(1, selectedFile.value.filename);
  policy.value = response.data
  await uploader.submit() // 手动上传
  formData.value.cover = policy.value.host + '/' + policy.value.key //拼接上传后的图片url
  return true
}

/**
 * 级联选择器选择后的回调
 */
function onChooseBoard() {
  formData.value.boardId = ''
  formData.value.pBoardId = ''
  formData.value.boardName = ''
  formData.value.pBoardName = ''
  setBoardInfo(selectedBoardId.value)
}

/**
 * 设置表单板块信息
 * @param ids 级联选择器所选中的板块id数组
 */
function setBoardInfo(ids) {
  // 选中了一级板块
  if (ids.length === 1) {
    formData.value.boardId = ids[0]
    boardStore.boardList.forEach(board => {
      if (board.boardId === ids[0]) {
        formData.value.boardName = board.boardName
      }
    })
    return
  }
  //选中了二级板块
  formData.value.boardId = ids[1]
  formData.value.pBoardId = ids[0]
  boardStore.boardList.forEach(board => {
    if (board.boardId === ids[0]) {
      formData.value.pBoardName = board.boardName
    }
    board.children.forEach((child => {
      if (child.boardId === ids[1]) {
        formData.value.boardName = child.boardName
      }
    }))
  })
}

/**
 * 将板块数据处理为el-cascader需要的对象
 */
const getBoardChild = (arr) => {
  if (arr === null || arr.length === 0) {
    return null
  }
  return arr.map(board => {
    return {
      value: board.boardId,
      label: board.boardName,
      children: getBoardChild(board.children)
    }
  })
}

/**
 * 提交表单
 */
async function handleSubmit(loader, form) {
  await form.validate() //表单校验
  let service = ElLoading.service({lock: true}); //设置页面为加载状态
  try {
    //上传图片到阿里云oss
    if (selectedFile.value.url !== '' && selectedFile.value.url !== null) {
      await handleUpload(loader)
    }
    // 设置表单数据，发起请求
    formData.value.content = valueHtml.value
    let response = await addArticleApi(formData.value);
    // 请求成功，清空表单数据
    clearObj(formData.value, selectedFile.value)
    ElMessage.success('发布成功，管理员正在审核')

    //跳转页面
    await router.push(`/article/${response.data.articleId}`)
  } finally {
    // 取消页面加载状态
    service.close()
  }

}

let options = ref()
let optionsVisibility = useElementVisibility(options);

/**
 * 滚动页面到 顶部/发布设置
 */
function handleViewRoll() {
  if (optionsVisibility.value) {
    window.scrollTo({top: 0, behavior: "smooth"})
  } else {
    let height = document.documentElement.scrollHeight;
    window.scrollTo({top: height, behavior: "smooth"})
  }
}


/**
 * wangEditor配置
 */
//模式
let mode = ref('default')

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef()

// 内容 HTML
const valueHtml = ref('<h1>hello</h1>')

// 工具栏实例
const toolbarConfig = {}
// 排除功能
toolbarConfig.excludeKeys = ['fullScreen']
// 编辑器配置
const editorConfig = {placeholder: '请输入内容...', title: 'hello'}

// 组件销毁时，也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})

const handleCreated = (editor) => {
  editorRef.value = editor // 记录 editor 实例，重要！
}
</script>

<style lang="scss" scoped>
@import "@/styles/var";

.edit-shell {
  max-width: $width-view-min;
  width: $width-view-min;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.editor-tool {
  position: fixed;
  z-index: 100;
}

.editor {
  width: 80%;
  min-height: 500px;
  max-width: 80%;
  overflow-x: auto;
  margin-top: 3rem;
  border: 1px solid #ccc;
}

.article-options {
  padding: 1rem;
  width: 80%;
  position: relative;
  bottom: 100px;
  background-color: #ffffff;

  .title {
    width: 500px;
  }

  .icon-uploader {
    width: 100px;
    height: 100px;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid #e1dede;
    border-radius: 5px;
    //background-color: #409eff;
  }
}

.footer-shell {
  width: 100%;
  padding: 1rem 10%;
  position: fixed;
  bottom: 0;
  background-color: #ffffff;

  .footer {
    max-width: $width-view-min;
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #a493a5;
    margin: 0 auto;

    .left {
      cursor: pointer;

      &:hover {
        color: #409eff;
      }
    }

    .right {
      span {
        margin-right: 1rem;
      }
    }
  }
}

// 封面上传
.uploader {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);

  &:hover {
    border-color: var(--el-color-primary);
  }

  .el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
  }
}


// 解决编辑器样式被覆盖问题
:deep(.w-e-text-container) {
  h1 {
    font-size: 2em;
    font-weight: bold;
  }

  h2 {
    font-size: 1.5em;
    font-weight: bold;
  }

  h3 {
    font-size: 1.17em;
    font-weight: bold;
  }

  h4 {
    font-size: 1em;
    font-weight: bold;
  }

  h5 {
    font-size: 0.83em;
    font-weight: bold;
  }

  b {
    font-weight: bold;
  }

  i {
    font-style: italic;
  }
}
</style>